import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
import java.util.List;

public class Node {

	private static Node nodeInstance;
	private ListeningService listeningService;
	private PrepareRequest prepareRequest = new PrepareRequest();
//	private BucketOperations bucketOperations = new BucketOperations();

	public static Node getInstance() {

		if (null == nodeInstance) {

			Node.nodeInstance = new Node();

		}

		return nodeInstance;

	}

	public ListeningService getListeningService() {
		if (null == listeningService) {
			try {
				this.listeningService = new ListeningService();
			} catch (UnknownHostException e) {

				e.printStackTrace();
			}
			Thread listen = new Thread(listeningService);
			listen.start();
		}
		return listeningService;
	}

	private Node() {

		this.getListeningService();

	}

	public void printSelfDetails() {

		System.out.println("\n\nMy Details");
		System.out.println("My ID:  " + SelfInfo.nodeTriple.nodeID);

		// Use when Binary is needed
		// System.out.println( new BigInteger(SelfInfo.nodeTriple.nodeID,
		// 16).toString(2));
		System.out.println("My IP:  "
				+ SelfInfo.listeningSocket.getLocalAddress());

		System.out.println("Listening Port:  "
				+ SelfInfo.listeningSocket.getLocalPort());
		System.out.println("Sending Port:  "
				+ SelfInfo.sendSocket.getLocalPort() + "\n\n");

	}

	public String readUserInput() throws IOException {

		String input = null;
		InputStreamReader inputStreamReader = new InputStreamReader(System.in);
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

		input = bufferedReader.readLine();

		return input;
	}

	public void displayOptions() throws IOException {

		String[] params = { "clear" };
		Runtime.getRuntime().exec(params);

		System.out.println("Kademlia client options");
		System.out.println("-----------------------------");
		System.out.println("1: PING");
		System.out.println("2: FIND NODE");
		System.out.println("3: DISPLAY K-BUCKETS");
		System.out.println("4: EXIT");
		System.out.println("5: DISPLAY SELF-PROPERTIES");
		System.out.println("6: JOIN");
		System.out.println("-----------------------------");
	}

	public void processUserOption(String input) throws Exception {

		if (null == input) {

			System.out.println("Invalid option.");
			return;
		}

		int option = Integer.parseInt(input);

		switch (option) {

		case 1:
			System.out.println("Available IDs");
			bucketOperations.printAllBucketEntries();
			NodeTriple nodeTriple = new NodeTriple();
			System.out.println("Enter ID");
			nodeTriple.nodeID = readUserInput();
			System.out.println("Enter IP");
			nodeTriple.ip = new PrepareResponse()
					.ipFromString(readUserInput());
			System.out.println("Enter port");
			nodeTriple.port = Integer.parseInt(readUserInput());
			prepareRequest.pingSomeOne(nodeTriple);
			break;
		case 2:
			System.out.println("FIND NODE");
			System.out.println("Node ID to search:");
			String userSearchId = readUserInput();
			List<NodeTriple> nodeTriples = bucketOperations
					.getListOfNodesForFindNodeRequest(userSearchId);
			for (NodeTriple eacNodeTriple : nodeTriples) {
				prepareRequest.sendFindNodeRequest(userSearchId, eacNodeTriple);
			}
			break;
		case 3:
			System.out.println("MY BUCKETS:");
			bucketOperations.printAllBucketEntries();
			break;
		case 4:
			System.out.println("Bye! Bye!");
			System.exit(0);
		case 5:
			this.printSelfDetails();
			break;
		case 6:
			System.out
					.println("Enter known Node details.(To simulate bootstrapping)");
			NodeTriple tripleForJoin = new NodeTriple();
			System.out.println("Enter ID");
			tripleForJoin.nodeID = readUserInput();
			System.out.println("Enter IP");
			tripleForJoin.ip = new PrepareResponse()
					.ipFromString(readUserInput());
			System.out.println("Enter port");
			tripleForJoin.port = Integer.parseInt(readUserInput());

			prepareRequest.sendFindNodeRequest(SelfInfo.nodeTriple.nodeID,
					tripleForJoin);
			break;
		default:
			System.out.println("Invalid option");
			break;

		}

	}
}
